home *** CD-ROM | disk | FTP | other *** search
- /*
- File: ShimSerialHAL.c
-
- Contains: Routines for controlling the underlying hardware (HAL - Hardware Abstraction Layer)
-
- Version: xxx put version here xxx
-
- Written by:
-
- Copyright: © 1994-1998 by Apple Computer, Inc., all rights reserved.
-
- File Ownership:
-
- DRI: xxx put dri here xxx
-
- Other Contact: xxx put other contact here xxx
-
- Technology: USB
-
- */
-
- #include <Gestalt.h>
- #include <Errors.h>
-
- #include "Modem.h"
- #include "ShimSerialHAL.h"
- #include "ModemDriver.h"
-
- /************************************************************************************/
- //
- // SerHAL_Entry
- //
- // This is the main driver entry point.
- //
- /************************************************************************************/
-
- OSErr SerHAL_Entry(UInt16 HdwSelector, ParmBlkPtr pb, UInt32 RefCon)
- {
- #pragma unused (RefCon)
- OSErr err = noErr;
-
- switch (HdwSelector)
- {
- case SerHAL_Initialize:
- // only do the open stuff once per driver pair
- if (gGlobals->openSession == false)
- err = HAL_DoOpenSession();
- break;
-
- case SerHAL_Terminate:
- // only do the close stuff once per driver pair
- if (gGlobals->openSession)
- err = HAL_DoCloseSession();
- break;
-
- case SerHAL_Read:
- // attempt to fill read request immediately
- // from any pending data in the input buffer
- err = HAL_FillReadRequest((IOParam*)pb);
- HAL_InputFlowControl();
- // if it's not completed (pending) save the pb
- if (err > noErr)
- gGlobals->pbIn = pb;
- break;
-
- case SerHAL_Write:
- err = USBSerialWrite((IOParam*)pb);
- if (err > noErr)
- gGlobals->pbOut = pb;
- break;
-
- case SerHAL_SetConfiguration:
- err = HAL_SetConfiguration(*(UInt16*)pb->cntrlParam.csParam);
- break;
-
- case SerHAL_SetInputBuffer:
- err = HAL_SetInputBuffer(*(Ptr*)pb->cntrlParam.csParam, *(UInt16*)(((Ptr)pb->cntrlParam.csParam) + 4));
- break;
-
- case SerHAL_SetFlowControl:
- HAL_SetFlowControl((SerShk*)pb->cntrlParam.csParam, pb->cntrlParam.csCode);
- break;
-
- case SerHAL_SetBreak:
- USBSendBreak((pb->cntrlParam.csCode == kSERDSetBreak));
- break;
-
- case SerHAL_SetDTERate:
- // check csCode first to see what the real rate is
- if (pb->cntrlParam.csCode == kSERD115KBaud)
- {
- *(UInt16*)pb->cntrlParam.csParam = HAL_SetDTERate(115200);
- } else {
- if (pb->cntrlParam.csCode == kSERD230KBaud)
- {
- *(UInt16*)pb->cntrlParam.csParam = HAL_SetDTERate(23400);
-
- } else {
- *(UInt16*)pb->cntrlParam.csParam = HAL_SetDTERate(*(UInt16*)pb->cntrlParam.csParam);
- }
- }
- break;
-
- case SerHAL_SetDTR:
- USBSetDTRState((pb->cntrlParam.csCode == kSERDAssertDTR));
- USBSetControlLineState();
- break;
-
- case SerHAL_SetParity:
- HAL_SetParity((pb->cntrlParam.csCode == kSERDSetPEAltChar), *(unsigned char*)pb->cntrlParam.csParam, *(((unsigned char*)pb->cntrlParam.csParam)+1));
- break;
-
- case SerHAL_SetXOffFlag:
- HAL_SetXOffFlag(pb->cntrlParam.csCode == kSERDSetXOffFlag);
- break;
-
- case SerHAL_SendXOn:
- HAL_SendXOn((pb->cntrlParam.csCode == kSERDSendXOn));
- break;
-
- case SerHAL_SendXOff:
- HAL_SendXOff((pb->cntrlParam.csCode == kSERDSendXOff));
- break;
-
- case SerHAL_Miscellaneous:
- // only interested in DTR (for now)
- if ((UInt8)pb->cntrlParam.csParam[0] & kOptionPreserveDTR)
- {
- USBSetCloseDTR();
- }
- break;
-
- case SerHAL_GetBuffer:
- *(UInt32*)(&pb->cntrlParam.csParam[0]) = HAL_GetBuffer();
- break;
-
- case SerHAL_GetStatus:
- HAL_GetStatus((SerStaRec*)pb->cntrlParam.csParam);
- break;
-
- case SerHAL_GetVersion:
- // need to understand this - 9 implies that we do > 57.6K
- *(char *)pb->cntrlParam.csParam = 9;
- break;
-
- case SerHAL_ControlExtend:
- err = HAL_ControlExtend(pb);
- break;
-
- case SerHAL_StatusExtend:
- err = HAL_StatusExtend(pb);
- break;
-
- default:
- err = -1; // unknown selector (for now)
- break;
- }
-
- return err;
- }
-
- /************************************************************************************/
- //
- // HAL_SetConfiguration
- //
- // Serial driver SerReset control call.
- //
- /************************************************************************************/
-
- OSErr HAL_SetConfiguration(UInt16 config)
- {
-
- UInt16 baudRate;
- LineParms Line_Coding;
-
- TraceMessage(0,"\pEntering HAL_SetConfiguration");
-
- switch (config & kSerConfigBaudMask)
- {
- case baud300: baudRate = 300; break;
- case baud600: baudRate = 600; break;
- case baud1200: baudRate = 1200; break;
- case baud1800: baudRate = 1800; break;
- case baud2400: baudRate = 2400; break;
- case baud3600: baudRate = 3600; break;
- case baud4800: baudRate = 4800; break;
- case baud7200: baudRate = 7200; break;
- case baud9600: baudRate = 9600; break;
- case baud19200: baudRate = 19200; break;
- case baud38400: baudRate = 38400; break;
- case baud57600: baudRate = 57600; break;
- default: baudRate = 57600; break;
- }
-
- Line_Coding.DTERate1 = USBToHostWord(baudRate); // All because of Intel format
- Line_Coding.DTERate2 = 0;
-
- switch (config & kSerConfigLenMask)
- {
- case data5:
- Line_Coding.DataBits = k5DataBits;
- break;
- case data6:
- Line_Coding.DataBits = k6DataBits;
- break;
- case data7:
- Line_Coding.DataBits = k7DataBits;
- break;
- case data8:
- Line_Coding.DataBits = k8DataBits;
- break;
- default:
- Line_Coding.DataBits = k8DataBits;
- break;
- }
-
- switch (config & kSerConfigParityMask)
- {
- case noParity:
- Line_Coding.ParityType = kNoParity;
- break;
- case oddParity:
- Line_Coding.ParityType = kOddParity;
- break;
- case evenParity:
- Line_Coding.ParityType = kEvenParity;
- break;
- default:
- Line_Coding.ParityType = kNoParity;
- break;
- }
-
- switch (config & kSerConfigStopMask)
- {
- case stop10:
- Line_Coding.CharFormat = k1StopBit;
- break;
- case stop15:
- Line_Coding.CharFormat = k15StopBits;
- break;
- case stop20:
- Line_Coding.CharFormat = k2StopBits;
- break;
- default:
- Line_Coding.CharFormat = k1StopBit;
- break;
- }
-
- // reset the baud rate and other values
-
- USBSetLineCoding(Line_Coding);
-
- return noErr;
- }
-
- /************************************************************************************/
- //
- // HAL_SetInputBuffer
- //
- // Select and initialize the serial input buffer.
- //
- /************************************************************************************/
-
- OSErr HAL_SetInputBuffer(Ptr newBuf, UInt16 bufLen)
- {
- OSErr err;
- long result;
- Boolean vmPresent;
-
- TraceMessage(0,"\pEntering HAL_SetInputBuffer");
-
- // check for presence of virtual memory
-
- err = Gestalt(gestaltVMAttr,&result);
- vmPresent = ((err == noErr) && (result >= gestaltVMPresent));
-
- // un-hold any previous input buffer
-
- if (vmPresent && gGlobals->inBufPtr && (gGlobals->inBufPtr != gGlobals->builtInBuffer))
- UnholdMemory(gGlobals->inBufPtr, gGlobals->inBufLen);
-
- // assign our local buffer as the default
-
- gGlobals->inBufPtr = gGlobals->builtInBuffer;
- gGlobals->inBufLen = kBuiltInBufferSize;
-
- // reset buffer indexes
-
- gGlobals->inBufStartIndex = 0;
- gGlobals->inBufEndIndex = 0;
-
- // a non-zero buffer length means use client buffer
- // a zero buffer length means use the default buffer
-
- if (bufLen && newBuf)
- {
- // we need to make sure the buffer stays in physical memory
-
- if (vmPresent)
- {
- err = HoldMemory(newBuf, bufLen);
- if (err != noErr)
- return err;
- }
-
- // assign client buffer
- gGlobals->inBufPtr = (UInt8 *) newBuf;
- gGlobals->inBufLen = bufLen;
- }
-
- return noErr;
- }
-
- /************************************************************************************/
- //
- // HAL_SetFlowControl
- //
- // Process the csSerHShake & csSerHShakeDTR control calls.
- //
- /************************************************************************************/
-
- void HAL_SetFlowControl(SerShk *shkNew, UInt16 csCode)
- {
-
- TraceMessage(0,"\pEntering HAL_SetFlowControl");
-
- //
- // set new cts value
- //
-
- gGlobals->serShk.fCTS = shkNew->fCTS;
-
- //
- // copy over new xon / xoff characters
- //
-
- gGlobals->serShk.xOn = shkNew->xOn;
- gGlobals->serShk.xOff = shkNew->xOff;
-
- //
- // handle any change in software output flow control
- // this is ignored for now
-
- gGlobals->serShk.fXOn = 0;
-
- // copy over the errs & evts options fields
- // notice we do _nada_ with the events (no _PostEvent, etc.)
-
- gGlobals->serShk.errs = shkNew->errs & (parityErr | hwOverrunErr | framingErr);
- gGlobals->serShk.evts = shkNew->evts;
-
- // handle any change in software input flow control
- // again this is ignored for now
-
- gGlobals->serShk.fInX = 0;
-
- // if csCode is newer kSERDHandshake,
- // take account of the fDTR field
-
- if (csCode == kSERDHandshake)
- {
-
- //
- // handle any change in hardware input flow control
- // ignored for now
- //
-
- gGlobals->serShk.fDTR = 1;
-
- }
- }
-
- /************************************************************************************/
- //
- // HAL_SendXOn
- //
- // Determines whether to send XOn character.
- // This is a stub for now
- //
- /************************************************************************************/
-
- void HAL_SendXOn(Boolean always)
- {
- #pragma unused (always)
-
- TraceMessage(0,"\pEntering HAL_SendXOn");
-
- }
-
- /************************************************************************************/
- //
- // HAL_SendXOff
- //
- // Determines whether to send XOff character.
- // This is a stub for now
- //
- /************************************************************************************/
-
- void HAL_SendXOff(Boolean always)
- {
- #pragma unused (always)
-
- TraceMessage(0,"\pEntering HAL_SendXOff");
-
- }
-
- /************************************************************************************/
- //
- // HAL_SendXOffFlag
- //
- // Determines whether to send XOff character.
- //
- /************************************************************************************/
-
- void HAL_SetXOffFlag(Boolean state)
- {
- #pragma unused (state)
-
- TraceMessage(0,"\pEntering HAL_SetXOffFlag");
-
- gGlobals->serStat.xOffHold = 0; // always off for now
-
- }
-
- /************************************************************************************/
- //
- // HAL_GetStatus
- //
- // Status routine fills in the SerStaRec record.
- //
- /************************************************************************************/
-
- void HAL_GetStatus(SerStaRec *statRec)
- {
-
- TraceMessage(0,"\pEntering HAL_GetStatus");
-
- // get & reset cumErrs
-
- statRec->cumErrs = gGlobals->serStat.cumErrs;
- gGlobals->serStat.cumErrs = 0;
-
- // has an xOff been sent to stop input?
-
- statRec->xOffSent = gGlobals->serStat.xOffSent;
-
- // is there a pending read request?
-
- statRec->rdPend = (gGlobals->pbIn != nil);
-
- // is there a pending write request?
-
- statRec->wrPend = (gGlobals->pbOut != nil);
-
- // cts & xOff output flow control hold flags
-
- statRec->ctsHold = false; // always false for now?
- statRec->xOffHold = gGlobals->serStat.xOffHold;
-
- }
-
- /************************************************************************************/
- //
- // HAL_GetBuffer
- //
- // status routine computes & returns the number of bytes pending in the receive buffer
- //
- /************************************************************************************/
-
- UInt32 HAL_GetBuffer(void)
- {
- SInt32 count;
-
- // TraceMessage(0,"\pEntering HAL_GetBuffer");
-
- count = ((SInt32)gGlobals->inBufEndIndex - (SInt32)gGlobals->inBufStartIndex);
-
- if ( count < 0 )
- count += gGlobals->inBufLen;
-
- return count;
- }
-
- /************************************************************************************/
- //
- // HAL_SetDTERate
- //
- /************************************************************************************/
-
- UInt16 HAL_SetDTERate(UInt32 baudRate)
- {
-
- TraceMessage(0,"\pEntering HAL_SetDTERate");
-
- // validate the requested baud rate
-
- if (baudRate)
- {
- if (baudRate > kMaxBaudRate)
- baudRate = kMaxBaudRate;
-
- gGlobals->baudRate = baudRate;
- } else {
- baudRate = gGlobals->baudRate;
- }
-
- USBSetBaudRate(baudRate);
-
- // return actual baud rate used (this is historical)
-
- return baudRate;
- }
-
- /************************************************************************************/
- //
- // HAL_SetParity
- //
- // Assigns parity error replacement character and alternate replacment character.
- // if peChar is zero then no parity error character substitution.
- // This is a stub for now
- //
- /************************************************************************************/
-
- void HAL_SetParity(Boolean alt, char peChar, char peAltChar)
- {
- #pragma unused (alt, peChar, peAltChar)
-
- TraceMessage(0,"\pEntering HAL_SetParity");
-
- }
-
- /************************************************************************************/
- //
- // HAL_FillReadRequest
- //
- // Attempts to copy requested bytes from the internal serial buffer into request
- // parameter block.
- //
- /************************************************************************************/
-
- OSErr HAL_FillReadRequest(IOParam *pb)
- {
- OSErr result;
- UInt16 endIndex;
- UInt16 startIndex;
-
- TraceMessage(0,"\pEntering HAL_FillReadRequest");
-
- result = 1;
- while (result > noErr)
- {
-
- // this can be interrupted to add data to the internal buffer
- // so we update inBufStartIndex and inBufEndIndex each time
- // if there is nothing in the input buffer, leave quietly
-
- endIndex = gGlobals->inBufEndIndex;
- startIndex = gGlobals->inBufStartIndex;
-
- if (startIndex == endIndex)
- break;
-
- // copy byte into read request buffer and bump actual count
-
- pb->ioBuffer[pb->ioActCount] = gGlobals->inBufPtr[startIndex];
- pb->ioActCount++;
-
- // now update internal buffer inBufStartIndex
-
- startIndex++;
-
- if (startIndex >= gGlobals->inBufLen)
- startIndex = 0;
-
- gGlobals->inBufStartIndex = startIndex;
-
- // lastly, check if we've satisfied the request
-
- if (pb->ioReqCount <= pb->ioActCount)
- result = noErr;
- }
-
- return result;
- }
-
- /************************************************************************************/
- //
- // HAL_EnableSerialDevice
- //
- // Called once at driver open time to configure the hardware and get things going etc.
- //
- /************************************************************************************/
-
- void HAL_EnableSerialDevice(void)
- {
-
- TraceMessage(0,"\pEntering HAL_EnableSerialDevice");
-
- USBSetRTSState(1);
- USBSetDTRState(1);
-
- USBSetControlLineState();
-
- HAL_SetDTERate(0);
-
- // Start the read mechanism
-
- USBStartReadPolling();
-
- }
-
- /************************************************************************************/
- //
- // HAL_DisableSerialDevice
- //
- // Called once when the driver is closed to shut things down
- //
- /************************************************************************************/
-
- void HAL_DisableSerialDevice(void)
- {
-
- TraceMessage(0,"\pEntering HAL_DisableSerialDevice");
-
- USBStopReadPolling();
-
- USBSetRTSState(0);
- USBSetDTRState(0);
-
- USBSetControlLineState();
-
- }
-
- /************************************************************************************/
- //
- // HAL_InputFlowControl
- //
- // Handles hardware (dtr or rts) and software (xon / xoff) input flow control
- // This is a stub for now
- //
- /************************************************************************************/
-
- void HAL_InputFlowControl(void)
- {
-
- TraceMessage(0,"\pEntering HAL_InputFlowControl");
-
- }
-
- /************************************************************************************/
- //
- // HAL_EnableInput
- //
- // Sets the DTR state
- // This is a stub for now
- //
- /************************************************************************************/
-
- void HAL_EnableInput(Boolean enable)
- {
- #pragma unused (enable)
-
- TraceMessage(0,"\pEntering HAL_EnableInput");
-
- }
-
- /************************************************************************************/
- //
- // HAL_EnableOutput
- //
- // Handles output flow control
- // This is a stub for now
- //
- /************************************************************************************/
-
- void HAL_EnableOutput(void)
- {
-
- TraceMessage(0,"\pEntering HAL_EnableOutput");
-
- }
-
- /************************************************************************************/
- //
- // HAL_DoOpenSession
- //
- // Process an OpenDriver request to the stub drivers
- //
- /************************************************************************************/
-
- OSErr HAL_DoOpenSession(void)
- {
-
- OSErr err;
- LineParms Line_Coding;
-
- TraceMessage(0,"\pEntering HAL_DoOpenSession");
-
- // only allow one open session
-
- if (gGlobals->openSession)
- return openErr;
-
- // reset internal indexes, buffers, etc.
-
- err = HAL_SetInputBuffer(nil, 0);
- if (err)
- return openErr;
-
- // since we've cleared the buffer to zero initially we have to explicitly
- // initialize the baudRate
-
- gGlobals->baudRate = kMaxBaudRate;
-
- // reset default values for other variables
-
- gGlobals->xOnOffChar = 0;
- gGlobals->peChar = 0;
- gGlobals->peAltChar = 0;
-
- // reset handshake default values as per scc serial driver
-
- gGlobals->serShk.fXOn = 0;
- gGlobals->serShk.fCTS = 1;
- gGlobals->serShk.xOn = 0;
- gGlobals->serShk.xOff = 0;
- gGlobals->serShk.evts = 0;
- gGlobals->serShk.fInX = 0;
- gGlobals->serShk.fDTR = 1;
-
- // reset serial status record
-
- gGlobals->serStat.cumErrs = 0;
- gGlobals->serStat.xOffSent = 0;
- gGlobals->serStat.rdPend = 0;
- gGlobals->serStat.wrPend = 0;
- gGlobals->serStat.ctsHold = 0;
- gGlobals->serStat.xOffHold = 0;
-
- // Line coding structure
-
- Line_Coding.DTERate1 = 0; // gets handled later with
- Line_Coding.DTERate2 = 0; // value from gGlobals->baudRate
- Line_Coding.CharFormat = k1StopBit;
- Line_Coding.ParityType = kNoParity;
- Line_Coding.DataBits = k8DataBits;
-
- InitLineCoding(Line_Coding);
-
- // Let's get started
-
- HAL_EnableSerialDevice();
-
- // we now have an open session
-
- gGlobals->openSession = true;
-
- return noErr;
- }
-
- /************************************************************************************/
- //
- // HAL_DoCloseSession
- //
- // Process a CloseDriver request to the stub drivers
- //
- /************************************************************************************/
-
- OSErr HAL_DoCloseSession(void)
- {
-
- TraceMessage(0,"\pEntering HAL_DoCloseSession");
-
- HAL_DisableSerialDevice();
-
- // reset internal indexes, buffers, etc. - this
- // is important for vm to unhold memory on any
- // buffer the client may have requested earlier
-
- HAL_SetInputBuffer(nil, 0);
-
- // we no longer have an open session
-
- gGlobals->openSession = false;
-
- return noErr;
- }
-
- /************************************************************************************/
- //
- // HAL_ControlExtend
- //
- // User extensions to control
- //
- /************************************************************************************/
-
- OSErr HAL_ControlExtend(ParmBlkPtr pb)
- {
-
- TraceMessage(0,"\pEntering HAL_ControlExtend");
-
- if (pb->cntrlParam.csCode == kpciGetDCD)
- {
- ((char *)(pb->cntrlParam.csParam))[6] = USBGetDCDValue();
- return noErr;
- }
-
- return controlErr;
- }
-
- /************************************************************************************/
- //
- // HAL_StatusExtend
- //
- // User extensions to status
- //
- /************************************************************************************/
-
- OSErr HAL_StatusExtend(ParmBlkPtr pb)
- {
- #pragma unused (pb)
-
- TraceMessage(0,"\pEntering HAL_StatusExtend");
-
- return statusErr;
- }
-
-
- /************************************************************************************/
- //
- // HAL_ShimInput
- //
- // Handles the coordination of input and the requestors buffer.
- //
- /************************************************************************************/
-
- void HAL_ShimInput(UInt8 *buf, UInt32 count)
- {
- IOParam *pb;
- OSErr result;
- register UInt16 nextIndex;
- register unsigned char rcvByte;
- unsigned char cumErrs;
-
- TraceMessage(0,"\pEntering ShimInput");
-
- // set return result to incomplete
-
- result = 1;
- cumErrs = 0;
-
- while (count--)
- {
-
- // handle reading of data available in the hardware receive buffer
-
- rcvByte = *buf++;
-
- // compute index into our input buffer
-
- nextIndex = gGlobals->inBufEndIndex + 1;
- if ( nextIndex >= gGlobals->inBufLen )
- nextIndex = 0;
-
- // stuff the character into the input buffer and update the index
-
- gGlobals->inBufPtr[gGlobals->inBufEndIndex] = rcvByte;
- gGlobals->inBufEndIndex = nextIndex;
-
- // check for input buffer overflow
-
- if (gGlobals->inBufEndIndex == gGlobals->inBufStartIndex)
- {
- // mark that we've had an overrun
-
- gGlobals->serStat.cumErrs |= swOverrunErr;
- cumErrs |= swOverrunErr;
-
- // drop oldest character from our internal buffer
-
- gGlobals->inBufStartIndex++;
- if (gGlobals->inBufStartIndex >= gGlobals->inBufLen)
- gGlobals->inBufStartIndex = 0;
-
- // we've had a software overrun -- we quit now and let the
- // client get a chance to read in the existing bytes --
- }
-
- // check for an outstanding read request
-
- pb = (IOParam *)gGlobals->pbIn;
- if (pb)
- {
- // copy bytes from input buffer into pb read buffer
- // (result is either 1=incomplete or 0=complete)
-
- result = HAL_FillReadRequest(pb);
-
- // handle errors that cause read aborts
-
- if (cumErrs & gGlobals->serShk.errs)
- result = rcvrErr;
-
- // if we have fulfilled this read request, we
- // need to call IOCommandIsComplete on it
- // and continue processing with the next request
-
- if ( result <= noErr )
- {
- gGlobals->pbIn = nil;
- break;
- }
- }
- }
-
- // clean up after ourselves
- if (result <= noErr)
- ShimIOComplete((union ParamBlockRec *)pb, result);
- }